package edu.pku.sei.mte.compositetrans.flow;

import java.util.ArrayList;
import java.util.List;

public class FlowController {
	
	public final static FlowNode END_OF_FLOW = new FlowNode(){
		public String toString(){
			return "END_OF_FLOW";
		}
		@Override
		public FlowNode getNext() {
			return null;
		}
	};
	public final static FlowNode WRONG_OF_FLOW = new FlowNode(){
		public String toString(){
			return "WRONG_OF_FLOW";
		}
		@Override
		public FlowNode getNext() {
			return null;
		}
	};
	
	private List<FlowNode> FlowPaths = new ArrayList<FlowNode>();
	private InitialNode firstNode = null;
	
	public void addNewPath(FlowNode fn){
		FlowPaths.add(fn);
	}
	
	private FlowNode getANewReadyPath(){
		for(FlowNode fn : FlowPaths){
			if(fn.isReady()){
				FlowPaths.remove(fn);
				return fn;
			}
		}
		return WRONG_OF_FLOW;
	}
	
	public boolean launch() throws Exception{
		FlowNode cfn = firstNode.getNext();
		while(cfn != END_OF_FLOW && cfn != WRONG_OF_FLOW){
			if(cfn.isReady()){
				if(cfn.execute()){
					cfn = cfn.getNext();
				}else{
					return false;
				}
			}else{
				addNewPath(cfn);
				cfn = getANewReadyPath();
			}
		}
		if(cfn == WRONG_OF_FLOW)
			return false;
		return true;
	}
	
	public static InitialNode createInitialNode(){
		return new InitialNode();
	}
	public static ActivityFinal createActivityFinal(){
		return new ActivityFinal();
	}
	public static ForkNode createForkNode(){
		return new ForkNode();
	}
	public static JoinNode createJoinNode(){
		return new JoinNode();
	}
	public static TActionNode createTActionNode(){
		return new TActionNode();
	}
	public static TDecisionNode createTDecisionNode(){
		return new TDecisionNode();
	}

	public void setFirstNode(InitialNode firstNode) {
		this.firstNode = firstNode;
	}
}
